﻿#include <qg/qg.h>

#define _USEATTRIB	1

using namespace tpl;

// D11 세이더 코드
const char D11ShaderCode[] = \
"cbuffer Constants : register(b0)"\
"{"\
"	float4x4 sWorldViewProj;"\
"};"\
"struct VSINPUT "\
"{"\
"	float3 pos : POSITION;"\
"	float4 color : COLOR;"\
"};"\
"struct VSOUTPUT "\
"{"\
"	float4 pos : SV_Position;"\
"	float4 color : COLOR;"\
"};"\
"VSOUTPUT VS(VSINPUT i) "\
"{"\
"	VSOUTPUT o;"\
"	o.pos = mul(float4(i.pos, 1.0f), sWorldViewProj);"\
"	o.color = i.color;"\
"	return o;"\
"}"\
"float4 PS(VSOUTPUT i) : SV_Target"\
"{"\
"	return i.color;	"\
"}";

// DX9 세이더 코드
const char DX9ShaderCode[] = \
"float4x4 sWorldViewProj;"\
"struct VSINPUT "\
"{"\
"	float3 pos : POSITION;"\
"	float4 color : COLOR;"\
"};"\
"struct VSOUTPUT "\
"{"\
"	float4 pos : POSITION;"\
"	float4 color : COLOR;"\
"};"\
"VSOUTPUT VS(VSINPUT i) "\
"{"\
"	VSOUTPUT o;"\
"	o.pos = mul(float4(i.pos, 1.0f), sWorldViewProj);"\
"	o.color = i.color;"\
"	return o;"\
"}"\
"float4 PS(VSOUTPUT i) : COLOR"\
"{"\
"	return i.color;	"\
"}";

// GLSL 세이더 코드
const char GlslVertexCode[] = \
"uniform mat4 sWorldViewProj;\n" \
"varying vec4 vcolor;\n" \
"void main()\n" \
"{\n" \
"	gl_Position = sWorldViewProj * gl_Vertex;\n" \
"	vcolor = gl_Color;\n" \
"}\n";

const char GlslAttributeCode[] = \
"uniform mat4 sWorldViewProj;\n" \
"attribute vec4 aposition;\n" \
"attribute vec4 acolor;\n" \
"varying vec4 vcolor;\n" \
"void main()\n" \
"{\n" \
"	gl_Position = sWorldViewProj * aposition;\n" \
"	vcolor = acolor;\n" \
"}\n";

const char GlslFragmentCode[] = \
"varying vec4 vcolor;\n" \
"void main()\n" \
"{\n" \
"	gl_FragColor = vcolor;\n" \
"}\n";

// ES2 세이더 코드
const char ES2VertexCode[] = \
"uniform mat4 sWorldViewProj;\n" \
"attribute vec4 aposition;\n" \
"attribute vec4 acolor;\n" \
"varying vec4 vcolor;\n" \
"void main()\n" \
"{\n" \
"	gl_Position = sWorldViewProj * aposition;\n" \
"	vcolor = acolor;\n" \
"}\n";

const char ES2FragmentCode[] = \
"precision mediump float;\n"\
"varying vec4 vcolor;\n" \
"void main()\n" \
"{\n" \
"	gl_FragColor = vcolor;\n" \
"}\n";

// 정점 형식
struct Vertex
{
	tpl::Vec3			pos;
	tpl::Color			color;
};

int main(void)
{
	k_mesg("DRAW BOX TEST\n");

	qgDevice* dev = qgDevice::New("es2", 640, 480, QGSDF_MSAA | QGSDF_LAYOUT | QGSDF_AUTO);

	if (dev)
	{
		tpl::BlueStr<64> devname(dev->GetDeviceName());
		dev->Mount(QG_WORK_PATH);

		qgStub* stub = dev->GetStub();
		qgFreeType* font = qgFreeType::New();

		qgTexture* tex = dev->CreateTexture("/texture/z.png", QGTEXF_S2D);

		// 래스터라이저
		qgRasz* rasz = dev->CreateRasz(qgRaszDataEx());

		// 레이아웃
		qgLayoutElement le[] =
		{
			{QGDLOU_POSITION, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_COLOR, 0, QGDLOT_FLOAT4, 0, 0, },
		};
		qgLayout* lo = dev->CreateLayout(le);

		// 세이더
		qgShader* shd = dev->CreateShader(NULL);
		if (shd)
		{
			if (devname.Contains("D11"))
			{
				shd->BindData(QGSHADER_PS, D11ShaderCode, sizeof(D11ShaderCode), 0);
				shd->BindData(QGSHADER_VS, D11ShaderCode, sizeof(D11ShaderCode), 0);
			}
			else if (devname.Contains("DX9"))
			{
				shd->BindData(QGSHADER_PS, DX9ShaderCode, sizeof(DX9ShaderCode), 0);
				shd->BindData(QGSHADER_VS, DX9ShaderCode, sizeof(DX9ShaderCode), 0);
			}
			else if (devname.Contains("GL"))
			{
				shd->BindData(QGSHADER_PS, GlslFragmentCode, sizeof(GlslFragmentCode), 0);
#if _USEATTRIB
				shd->BindData(QGSHADER_VS, GlslAttributeCode, sizeof(GlslAttributeCode), 0);
#else
				shd->BindData(QGSHADER_VS, GlslVertexCode, sizeof(GlslVertexCode), 0);
#endif
			}
			else if (devname.Contains("ES"))
			{
				shd->BindData(QGSHADER_PS, ES2FragmentCode, sizeof(ES2FragmentCode), 0);
				shd->BindData(QGSHADER_VS, ES2VertexCode, sizeof(ES2VertexCode), 0);
			}
			else
			{
				shd->Unload();
				shd = NULL;
			}
			//shd->Link();
		}

		// 꼭지점
		Vertex vts[] =
		{
			{tpl::Vec3(-1.0f, -1.0f, -1.0f), tpl::Colors::White},
			{tpl::Vec3(-1.0f, +1.0f, -1.0f), tpl::Colors::Black},
			{tpl::Vec3(+1.0f, +1.0f, -1.0f), tpl::Colors::Red},
			{tpl::Vec3(+1.0f, -1.0f, -1.0f), tpl::Colors::Green},
			{tpl::Vec3(-1.0f, -1.0f, +1.0f), tpl::Colors::Blue},
			{tpl::Vec3(-1.0f, +1.0f, +1.0f), tpl::Colors::Yellow},
			{tpl::Vec3(+1.0f, +1.0f, +1.0f), tpl::Colors::Cyan},
			{tpl::Vec3(+1.0f, -1.0f, +1.0f), tpl::Colors::Magenta}
		};
		qgBuffer* vb = dev->CreateVertexBuffer(vts, lo, 0, 0);

		// 인덱스
		kuint idx[] =
		{
			0, 1, 2, 0, 2, 3,
			4, 6, 5, 4, 7, 6,
			4, 5, 1, 4, 1, 0,
			3, 2, 6, 3, 6, 7,
			1, 5, 6, 1, 6, 2,
			4, 0, 3, 4, 3, 7,
		};
		qgBuffer* ib = dev->CreateIndexBuffer(idx, 0);

		//
		float ang = 0.0f;

		//
		while (dev->Run())
		{
			float adv = stub->GetAdvance();

			ang = k_cprad(ang + KM_PI_HALF*adv);

			tpl::Mat4 m = tpl::Mat4::Rotation(ang, ang, 0.0f);
			//tpl::Mat4 m = tpl::Mat4::RotationX(ang);
			m.ReplaceLocation(0.0f, 0.0f, 4.0f);

			//
			dev->Enter();

			dev->SetTexture(0, NULL);
			dev->SetRasz(rasz);
			dev->SetShader(shd);
			dev->SetLayout(lo);
			dev->SetIndexBuffer(0, ib);
			dev->SetVertexBuffer(0, vb);
			dev->SetTopology(QGTPG_TRI_LIST);
			dev->SetTM(QGTMS_WORLD, m);
			dev->DrawIndexed(36, 0);

			Rect rt(Point(20, 20), Point(tex->GetWidth() / 2, tex->GetHeight() / 2));
			dev->DrawRect(rt, tpl::ColorValues::White, tex);

			font->WriteFormat(5, 5, 0, "[%.2f] %.0f", stub->GetRunFps(), k_todeg(ang));

			dev->Leave();
			dev->Flush();
		}

		font->Unload();
		dev->Unload();
	}

	return 0;
}

